import json
import sys
from PySide6.QtWidgets import (QApplication, QDialog, QFileDialog, QTableWidgetItem,QGroupBox,QScrollArea,
                             QLabel, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QFormLayout,
                             QWidget, QMessageBox, QComboBox, QHeaderView,QDialogButtonBox,QColorDialog)
from PySide6.QtCore import Qt, QDate, QTime, QDateTime, QPoint, QEvent,Signal
from PySide6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
from PySide6.QtGui import QGuiApplication, QColor,QKeySequence,QKeyEvent
from gui.utils.api import API
from gui.window.child_dialog.base_manager import TableWidget_Base_Datamanager,timestamp_to_string

class CategoryItemWidget(QWidget):
    """分类标签项控件"""
    def __init__(self, name="", color="#FF0000", shortcut="", parent=None):
        super().__init__(parent)
        self.main_layout = QHBoxLayout(self)
        self.main_layout.setContentsMargins(0, 0, 0, 0)
        
        # 颜色预览
        self.color_label = QLabel()
        self.color_label.setFixedSize(20, 20)
        
        # 名称输入
        self.name_edit = QLineEdit(name)
        self.name_edit.setPlaceholderText("分类名称")
        
        # 颜色选择
        self.color_btn = QPushButton("选择颜色")
        self.color_btn.setProperty("color", color)
        self.color_btn.clicked.connect(self.select_color)
        
        # 快捷键输入
        self.shortcut_edit = QLineEdit(shortcut)
        self.shortcut_edit.setMaximumWidth(50)
        self.shortcut_edit.setPlaceholderText("按快捷键...")
        self.shortcut_edit.setReadOnly(True)
        self.shortcut_edit.setFocusPolicy(Qt.StrongFocus)  # 确保能接收焦点
        
        # 删除按钮
        self.delete_btn = QPushButton("删除")
        self.delete_btn.setMaximumWidth(60)
        self.set_color(color)
        
        # self.main_layout.addWidget(self.color_label)
        self.main_layout.addWidget(self.color_btn)
        self.main_layout.addWidget(self.name_edit)
        self.main_layout.addWidget(self.shortcut_edit)
        self.main_layout.addWidget(self.delete_btn)
        self.setLayout(self.main_layout)
        
    def select_color(self):
        """选择颜色"""
        color = QColorDialog.getColor(QColor(self.color_btn.property("color")), self)
        if color.isValid():
            self.set_color(color.name())
            
    def set_color(self, color):
        """设置颜色并更新预览"""
        self.color_btn.setStyleSheet(f"background-color: {color}; border-radius: 3px;")
        self.color_btn.setProperty("color", color)
        
    def get_data(self):
        """获取分类数据"""
        return {
            "name": self.name_edit.text(),
            "color": self.color_btn.property("color"),
            "shortcut": self.shortcut_edit.text()
        }
    def keyPressEvent(self, event: QKeyEvent):
        """捕获键盘事件，解析快捷键组合"""
        # 只在快捷键输入框获得焦点时处理
        if not self.shortcut_edit.hasFocus():
            super().keyPressEvent(event)
            return
            
        # 忽略回车键（避免触发默认行为）
        if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
            event.accept()
            return
            
        # 解析修饰键（Ctrl、Shift、Alt、Meta）
        modifiers = []
        if event.modifiers() & Qt.ControlModifier:
            modifiers.append("Ctrl")
        if event.modifiers() & Qt.ShiftModifier:
            modifiers.append("Shift")
        if event.modifiers() & Qt.AltModifier:
            modifiers.append("Alt")
        if event.modifiers() & Qt.MetaModifier:  # Meta在Windows是Win键，Mac是Command键
            modifiers.append("Meta")
            
        # 解析普通键（过滤掉纯修饰键）
        key = event.key()
        if key in (Qt.Key_Control, Qt.Key_Shift, Qt.Key_Alt, Qt.Key_Meta):
            event.accept()
            return
            
        # 转换键值为字符串（使用QKeySequence的toString()方法）
        key_str = QKeySequence(key).toString().replace('&', '')  # 移除可能的加速器符号
        
        # 组合快捷键字符串（如"Ctrl+Shift+A"）
        if modifiers:
            shortcut_str = "+".join(modifiers) + "+" + key_str
        else:
            shortcut_str = key_str
            
        # 更新输入框
        self.shortcut_edit.setText(shortcut_str)
        event.accept()
        
class ProjectForm(QDialog):
    """项目表单对话框"""
    # 预设30种不同颜色
    DEFAULT_COLORS = [
        "#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#FF00FF", "#00FFFF", 
        "#800000", "#008000", "#000080", "#808000", "#800080", "#008080", 
        "#C0C0C0", "#808080", "#FF8000", "#80FF00", "#00FF80", "#0080FF", 
        "#8000FF", "#FF0080", "#FF4500", "#FFA500", "#FFFFE0", "#F0E68C", 
        "#FA8072", "#E9967A", "#F5DEB3", "#D2B48C", "#A0522D"
    ]
    def __init__(self, project=None, parent=None):
        super().__init__(parent)
        self.setWindowTitle("项目信息" + (" - 编辑" if project else " - 添加"))
        self.resize(400, 300)
        
        self.project = project or {}
        
        layout = QVBoxLayout(self)
        form_layout = QFormLayout()
        
        self.name_edit = QLineEdit(self.project.get("name", ""))
        self.desc_edit = QLineEdit(self.project.get("desc", ""))
        
        
        # 如果是编辑模式，禁止修改名称、描述和类型
        if project:
            self.name_edit.setReadOnly(True)
        #     self.desc_edit.setReadOnly(True)
        
        # 3. Attributes 配置区域
        self.attributes_group = QGroupBox("标签选项配置")
        attributes_layout = QVBoxLayout(self.attributes_group)
        
        # 标签类型选择
        label_type_layout = QHBoxLayout()
        self.label_type_combo = QComboBox()
        self.label_type_combo.currentTextChanged.connect(self.on_label_type_changed)
        self.label_type_combo.addItems(["区域注释","文件注释",])
        label_type_layout.addWidget(QLabel("注释类型:"))
        label_type_layout.addWidget(self.label_type_combo)
        
        # 注释方式选择
        self.categories_widget = QWidget()
        self.categories_layout = QVBoxLayout(self.categories_widget)
        self.categories_layout.setAlignment(Qt.AlignTop)
        self.categories_layout.setSpacing(5)
        self.annotation_method_combo = QComboBox()
        self.annotation_method_combo.addItems(["分类","OCR转写", ])
        self.annotation_method_combo.currentTextChanged.connect(self.on_annotation_method_changed)
        annotation_method_layout = QHBoxLayout()
        annotation_method_layout.addWidget(QLabel("注释方式:"))
        annotation_method_layout.addWidget(self.annotation_method_combo)
        
        # 添加分类按钮
        self.add_category_btn = QPushButton("添加分类")
        self.add_category_btn.clicked.connect(self.add_category)
        annotation_method_layout.addWidget(self.add_category_btn)
        
        # 分类列表区域
        self.categories_scroll = QScrollArea()
        self.categories_scroll.setWidgetResizable(True)
        self.categories_scroll.setWidget(self.categories_widget)
        
        # 加载已有分类或初始化默认分类
        if project and "attributes" in project and "categories" in project["attributes"]:
            for category in project["attributes"]["categories"]:
                self.add_category_item(
                    category.get("name", ""),
                    category.get("color", "#FF0000"),
                    category.get("shortcut", "")
                )
        else:
            # 初始化几个默认分类（仅在新建项目且选择"分类"时）
            self.on_annotation_method_changed(self.annotation_method_combo.currentText())
        
        attributes_layout.addLayout(label_type_layout)
        attributes_layout.addLayout(annotation_method_layout)
        attributes_layout.addWidget(QLabel("分类配置:"))
        attributes_layout.addWidget(self.categories_scroll)
        
        # 表单布局
        form_layout.addRow("名称:", self.name_edit)
        form_layout.addRow("描述:", self.desc_edit)
        form_layout.addRow(self.attributes_group)
        
        layout.addLayout(form_layout)
        
        # 按钮
        button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        layout.addWidget(button_box)
            
    def on_label_type_changed(self, text):
        """标签类型变更时的处理"""
        # 如果切换到"分类"，确保有分类项
        # if self.annotation_method_combo.currentText() == "分类" and self.categories_layout.count() == 0:
        #     self.add_category()
    
    def on_annotation_method_changed(self, text):
        """注释方式变更时的处理"""
        # 清除现有分类
        while self.categories_layout.count():
            item = self.categories_layout.takeAt(0)
            widget = item.widget()
            if widget:
                widget.deleteLater()
        if text == "分类":
            self.add_category_btn.setEnabled(True)
        else:
            self.add_category_btn.setEnabled(False)
        
    
    
    def add_category_item(self, name="", color="#FF0000", shortcut=""):
        """添加分类项"""
        item_widget = CategoryItemWidget(name, color, shortcut)
        item_widget.delete_btn.clicked.connect(lambda: self.remove_category(item_widget))
        self.categories_layout.addWidget(item_widget)
    
    def add_category(self):
        """添加新分类"""
        # 使用下一个可用的预设颜色
        used_colors = set()
        for i in range(self.categories_layout.count()):
            widget = self.categories_layout.itemAt(i).widget()
            if widget:
                used_colors.add(widget.color_btn.property("color"))
        
        next_color = "#FF0000"  # 默认红色
        for color in self.DEFAULT_COLORS:
            if color not in used_colors:
                next_color = color
                break
        
        # 添加新分类，使用下一个可用数字作为名称和快捷键
        new_index = self.categories_layout.count() + 1
        self.add_category_item(
            f"分类{new_index}",
            next_color,
            chr(ord('1') + new_index - 1) if new_index <= 9 else ""
        )
    
    def remove_category(self, widget):
        """删除分类"""
        self.categories_layout.removeWidget(widget)
        widget.deleteLater()
    
    def get_data(self):
        """获取表单数据"""
        # 收集分类列表
        categories = []
        for i in range(self.categories_layout.count()):
            widget = self.categories_layout.itemAt(i).widget()
            if widget:
                category_data = widget.get_data()
                if category_data["name"]:  # 只添加有名称的分类
                    categories.append(category_data)
        
        data = {
            "name": self.name_edit.text(),
            "desc": self.desc_edit.text(),
            "attributes": {
                "label_type": self.label_type_combo.currentText(),
                "annotation_method": self.annotation_method_combo.currentText(),
                "categories": categories  # 分类配置
            }
        }
        
        if self.project:  # 编辑模式
            data["id"] = self.project.get("id")
        return data


class TableWidget_Projects_manager(TableWidget_Base_Datamanager):
    def __init__(self, api: API):
        super().__init__(api)
        self.setWindowTitle("项目管理系统")
        self.resize(1000, 600)
        self.set_table_columns(["ID", "名称", "描述", "标签属性", "创建时间", "结束时间", "操作"])
    
    def setup_top_buttons(self):
        """设置顶部按钮"""
        self.add_button = QPushButton("添加项目")
        self.add_button.clicked.connect(self.add_project)
        self.top_button_layout.addStretch()
        self.top_button_layout.addWidget(self.add_button)
    
    
    def setup_search_fields(self):
        """设置搜索字段"""
        # 搜索框
        self.search_name_field = QLineEdit()
        self.search_name_field.setPlaceholderText("输入项目名称...")
        
        self.search_decs_field = QLineEdit()
        self.search_decs_field.setPlaceholderText("输入项目描述...")
        
        # 添加到搜索布局
        self.search_h1_layout.addWidget(self.search_name_field)
        self.search_h1_layout.addWidget(self.search_decs_field)
        

    def fill_table_row(self, row, item):
        """填充项目表格行数据"""
        
        id_item = QTableWidgetItem(str(item["id"]))
        id_item.setData(Qt.ItemDataRole.UserRole, item)
        self.table.setItem(row, 0, id_item)
        
        self.table.setItem(row, 1, QTableWidgetItem(item["name"]))
        self.table.setItem(row, 2, QTableWidgetItem(item["desc"]))
        attributes_item = QTableWidgetItem(json.dumps(item["attributes"]))
        attributes_item.setToolTip(json.dumps(item["attributes"],indent=4,ensure_ascii=False))
        self.table.setItem(row, 3, attributes_item)
        self.table.setItem(row, 4, QTableWidgetItem(timestamp_to_string(item["create_at"])))
        self.table.setItem(row, 5, QTableWidgetItem(timestamp_to_string(item["update_at"])))
        
        # 操作按钮
        edit_button = QPushButton("编辑")
        edit_button.clicked.connect(lambda checked, r=row: self.edit_project(r))
        delete_button = QPushButton("删除")
        delete_button.clicked.connect(lambda checked, r=row: self.delete_project(r))
        
        button_widget = QWidget()
        button_layout = QHBoxLayout(button_widget)
        button_layout.addWidget(edit_button)
        button_layout.addWidget(delete_button)
        button_layout.setContentsMargins(0, 0, 0, 0)
        self.table.setCellWidget(row, 6, button_widget)
    
    def get_query_params(self):
        """获取查询参数"""
        params = super().get_query_params()
        
        search_name_field_text = self.search_name_field.text().strip()
        search_decs_field_text = self.search_decs_field.text().strip()
        search_create_start_datetime, search_create_end_datetime = self.search_create_field.get_range()
        search_update_start_datetime, search_update_end_datetime = self.search_update_field.get_range()
        
        params.update({
            "name": search_name_field_text,
            "desc": search_decs_field_text,
            "create_at": [search_create_start_datetime, search_create_end_datetime],
            "update_at": [search_update_start_datetime, search_update_end_datetime],
        })
        
        return params
    
    
    def load_data(self):
        """加载项目数据"""
        query_params = self.get_query_params()
        self.api.query_projects(**query_params, callback=self.update_table)
    
    def add_project(self):
        """添加项目"""
        dialog = ProjectForm(parent=self)
        if dialog.exec():
            data = dialog.get_data()
            self.api.add_project(**data, callback=self.on_add_success)
    
    def update_upload_progress(self, bytes_sent, bytes_total):
        """更新上传进度"""
        if bytes_total > 0:
            progress = int((bytes_sent / bytes_total) * 100)
            print(f"上传中：{progress}% （{bytes_sent}/{bytes_total}字节）")
            # self.progress_bar.setValue(progress)
            # self.status_label.setText(f"上传中：{progress}% （{bytes_sent}/{bytes_total}字节）")

    def handle_upload_finished(self, reply :QNetworkReply):
        """处理上传完成（无论成功失败）"""
        # if reply != self.upload_reply:
        #     return  # 忽略非当前上传的回复

        # 读取响应数据
        try:
            response_data = reply.readAll().data().decode('utf-8')
            status_code = reply.attribute(QNetworkRequest.Attribute.HttpStatusCodeAttribute)
            
            if status_code == 200:
                self.status_label.setText("上传成功！")
                QMessageBox.information(self, "成功", f"文件上传成功\n响应：{response_data}")
            else:
                self.status_label.setText(f"上传失败（状态码：{status_code}）")
                QMessageBox.warning(self, "失败", f"上传失败\n状态码：{status_code}\n响应：{response_data}")
        except Exception as e:
            self.status_label.setText(f"处理响应失败：{str(e)}")
            QMessageBox.critical(self, "响应错误", f"无法解析服务器响应：{str(e)}")

        # # 清理
        # self.upload_reply = None
        # self.progress_bar.setValue(0)
        # self.upload_btn.setEnabled(True)  # 恢复按钮可用
        
    def on_add_success(self, response):
        """添加成功回调"""
        if response.get("code") == 0:
            QMessageBox.information(self, "成功", "项目添加成功")
            self.load_data()
        else:
            QMessageBox.critical(self, "失败", f"项目添加失败: {response.get('message', '未知错误')}")
    
    def edit_project(self, row):
        """编辑项目"""
        item = self.table.item(row, 0).data(Qt.ItemDataRole.UserRole)
        dialog = ProjectForm(item, parent=self)
        if dialog.exec():
            data = dialog.get_data()
            project_id = data.get("id")
            file_path = data.get("file_path")
            self.api.attach_file_projects(project_id=project_id,file_path=file_path, callback=self.on_add_success)
            # self.api.update_project(**data, callback=self.on_edit_success)
    
    def on_edit_success(self, response):
        """编辑成功回调"""
        if response.get("code") == 0:
            QMessageBox.information(self, "成功", "项目更新成功")
            self.load_data()
        else:
            QMessageBox.critical(self, "失败", f"项目更新失败: {response.get('message', '未知错误')}")
    
    def delete_project(self, row):
        """删除项目"""
        item = self.table.item(row, 0).data(Qt.ItemDataRole.UserRole)
        reply = QMessageBox.question(
            self, "确认删除", 
            f"确定要删除项目 '{item['name']}' 吗？",
            QMessageBox.Yes | QMessageBox.No
        )
        if reply == QMessageBox.Yes:
            self.api.del_project(project_id=item["id"], callback=self.on_delete_success)
            print(item)
    
    def on_delete_success(self, response):
        """删除成功回调"""
        if response.get("code") == 0:
            QMessageBox.information(self, "成功", "项目删除成功")
            self.load_data()
        else:
            QMessageBox.critical(self, "失败", f"项目删除失败: {response.get('message', '未知错误')}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = TableWidget_Datamanager()
    window.show()
    sys.exit(app.exec())